﻿using System.Collections.Generic;

namespace IndentationSplitter
{
    internal class IndentedTree
    {
        private readonly List<TreeNode> _indentationLevels = new List<TreeNode>(); 
        private readonly IndentedLine[] _lines;
        private int _currentLine;
        private int _prevIndentation;
        private readonly List<TreeNode> _baseLevel = new List<TreeNode>();

        public IndentedTree(string indentedText)
        {
            _lines = IndentedLine.GetLinesFromText(indentedText);
            _currentLine = 0;
            _prevIndentation = 0;
            ParseTree();
        }

        private void ParseTree()
        {
            while (NotDone)
            {
                var newNode = new TreeNode {Value = CurrentLine.Text};
                
                if (OnSameLevel)
                    AddSibling(newNode);
                else
                    AddToParent(newNode);
                
                SetLastAtLevel(CurrentLine.Indentation, newNode);

                GotoNextLine();
            }
        }

        private void AddToParent(TreeNode node)
        {
            if(CurrentLine.Indentation == 0)
                _baseLevel.Add(node);
            else
                _indentationLevels[CurrentLine.Indentation - 1].Children.Add(node);
        }


        private void AddSibling(TreeNode node)
        {
            if (_prevIndentation == 0)
                _baseLevel.Add(node);
            else
                _indentationLevels[CurrentLine.Indentation - 1].Children.Add(node);
        }

        private void SetLastAtLevel(int indentation, TreeNode node)
        {
            if (indentation >= _indentationLevels.Count)
                _indentationLevels.Add(node);
            else
                _indentationLevels[indentation] = node;
        }

        private void GotoNextLine()
        {
            _prevIndentation = CurrentLine.Indentation;
            _currentLine++;
        }

        private bool OnSameLevel
        {
            get { return _prevIndentation == CurrentLine.Indentation; }
        }

        private bool NotDone
        {
            get { return _currentLine < _lines.Length; }
        }

        private IndentedLine CurrentLine { get { return _lines[_currentLine]; } }

        public IEnumerable<TreeNode> RootItems { get { return _baseLevel; } }
    }
}